
package censo

import scala.collection.mutable.ArrayBuffer



class Censo(anioCenso: Int) {

  //tiene todos los registros 
  val _registros: ArrayBuffer[Registro] = new ArrayBuffer[Registro]
  var _departamentos:ArrayBuffer[Departamento]=_
  def registros = _registros
  def departamento=_departamentos
  def agregarRegistro(r: Registro) = registros.+=(r)

  //A
  def totalDeVentas(criterioDeFiltro:CriterioDeFiltroTrait): Double = this.pasarVentasAListaConCriterios(criterioDeFiltro).foldLeft(0.0)((contador, elemento) => contador + elemento)

  // devuelve una lista con todos los montosDeVentas de todos los registros en ese anio
   def pasarVentasAListaConCriterios(criterioDeFiltro:CriterioDeFiltroTrait): ArrayBuffer[Double] = (criterioDeFiltro.filtrarRegistros(this.registros).filter { r => (r.anio == anioCenso) }).map { a => a._montoTotalDeVentas }
  
  //B
  def totalDeGanancias(): Double = this.pasarGananciasALista.foldLeft(0.0)((contador, elemento) => contador + elemento)
  def pasarGananciasALista: ArrayBuffer[Double] = registros map { a => a._montoTotalDeGanancias }
  ///////////////////////*
  def totalSuperiorA(criterioAComparar:CriterioValorSuperiorA, valorAComparar:Double):Int= (this.registros.filter(r => criterioAComparar.criterio(r)>valorAComparar && r.anio==anioCenso )).size
  //////////////////////*		  
  //C
  def totalDeVentasSuperiorA(valorAComparar: Double): Int = this.totalSuperiorA(new CriterioValorSuperiorA() with CriterioComparadorXTotalDeVentas, valorAComparar)
  //D
  def totalDeGananciasSuperiorA(valorAComparar: Double): Int =  this.totalSuperiorA(new CriterioValorSuperiorA() with CriterioComparadorXMontoDeGanancia, valorAComparar)
  //E
  def totalDeTasaDeGananciaSuperiorA(valorAComparar: Double): Int =  this.totalSuperiorA(new CriterioValorSuperiorA() with CriterioComparadorXTasaDeGanancia, valorAComparar) 
  //F  
  def asociacionDeProvinciaYtotalDeVentas(): Map[String, Double] = {
    var resultado: Map[String, Double] = Map[String, Double]()
    this.registros.foreach { r: Registro => if (r.anio == anioCenso) resultado += (r.nombreDeLaProvincia -> r.montoTotalDeVentas) }
    return resultado
  }
  //G
  def nombreDeEmpresasQueSuperan(valorAComparar: Double): ArrayBuffer[String] = (this.registros.filter(r => r.nombreEmpresasConVentasMayorA(valorAComparar) && r.soyRegistroDeEmpresa)).map { r => r.nombreDeLaEmpresa }
  //H  verifica el a�o,luego arma una lista de fuente, y luego quita los repetidos
  def fuentesQueAportaronUnRegistro(anioComparar: Int): Set[Fuente] = ((this.registros.filter { r => r.anio == anioComparar }).map { r => r.getFuente }).toSet
  //I   busca registros por a�o,los ordena por tasa y pido el primero
  //--En el mensajeque sigue cuando se realiza criterioDeFiltro.filtrarRegistros, en el caso de que no se asigne ninguna clase que incorpore este trait, el trtait por defecto devuelve el mismo registro
  def nombreDeLAEmpresaconMayorGananciaEn(criterioDeFiltro:CriterioDeFiltroTrait,anioAComparar: Int): String = (criterioDeFiltro.filtrarRegistros(this.registros.filter(r => r.anio == anioAComparar && r.soyRegistroDeEmpresa))).sortBy(r => r.montoTotalDeGanancias).head.empresa.nombre

  //empresa Solida
  def laEmpresaEsSolida(unaEmpresa:Empresa):Boolean={
    this.registros.filter(r=> r._empresa ._nombreEmpresa ==unaEmpresa._nombreEmpresa ).foreach { r: Registro => if (!(r.tasaDeGanancia > 10)) return false }
  	true
  }
  //empresa Sospechosa
  def laEmpresaEsSospechosa(unaEmpresa:Empresa):Boolean={
    this.registros.filter(r=> r._empresa ._nombreEmpresa ==unaEmpresa._nombreEmpresa ).foreach { r: Registro => if (!(r.tasaDeGanancia > 85)) return false }
  	true
  }
  
  def agregarDepartamento(departamento:Departamento)={
    this._departamentos .+=:(departamento)
  }
  
 //El grupo de departamentos es homogeneo
  //Precondicion,tiene que haber por lo menos un elemento
 def esHomogeneoElGrupo(grupoDeDepartamento:ArrayBuffer[Departamento]):Boolean={
   var primerDepartamento:Departamento=grupoDeDepartamento.head
   grupoDeDepartamento.foreach{d:Departamento => if(!(d._Provincia ==primerDepartamento._Provincia )) return false}
   true
 }
 //incluye o no grupos de departamentos de una provincia
		def grupoIncluyeDepartamentos(departamentosAVerificar:ArrayBuffer[Departamento]):Boolean={
		 val miGrupoDeDepartamentos=this.departamento
		  departamentosAVerificar.foreach{d:Departamento =>if(!(miGrupoDeDepartamentos.contains(d)))return false}
		  true
		}
 //_________Ejercicio 2 - 3) item a_________________
/*En estos mentodos que siguen se demuestra en cada uno como se devuelve el total de ventas, dependiendo el criterio
 * 
 * */	
   def filtrarXProvincia(provincia:String):Double={this.totalDeVentas(new CriterioDeFiltroXProvincia(provincia))}
   def filtrarXDepartamento(departamento:Departamento):Double={this.totalDeVentas(new CriterioDeFiltroXDepartamento(departamento))}
   def filtrarXRegistrosQuePertenecenAUnGrupoDeDepartamentos(departamentos:ArrayBuffer[Departamento])={this.totalDeVentas(new CriterioDeFiltroXGrupoDeDepartamento(departamentos))}
   def filtrarXFuente(fuente:Fuente):Double={this.totalDeVentas(new CriterioDeFiltroXFuente(fuente))}

 //Ejercicio 2 - 3) item i
  /**En este mensaje yo coloco los criterios por parametro, al igual que los metodos anteriores1
   * 
   *def nombreDeLAEmpresaconMayorGananciaEn(criterioDeFiltro:CriterioDeFiltroTrait,anioAComparar: Int): String = (criterioDeFiltro.filtrarRegistros(this.registros.filter(r => r.anio == anioAComparar && r.soyRegistroDeEmpresa))).sortBy(r => r.montoTotalDeGanancias).head.empresa.nombre
   */
   
//   Para los items c), d), e), si tenemos varios registros para la misma empresa conocida, hay que contarlos
//todos
     def totalSuperiorAEnTodosLosAnios(criterioAComparar:CriterioValorSuperiorA, valorAComparar:Double):Int= (this.registros.filter(r => criterioAComparar.criterio(r)>valorAComparar)).size

//     Para el item g), que el conjunto de nombres de empresas conocidas no tenga repetidos.

       def nombreDeEmpresasQueSuperanSinRepetidos(valorAComparar: Double):Set[String]= this.nombreDeEmpresasQueSuperan(valorAComparar).toSet

}